﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Web.Mvc;

using mvcForum.Core;
using mvcForum.Core.Abstractions.Interfaces;
using mvcForum.Web.Controllers;
using mvcForum.Web.Extensions;
using mvcForum.Web.ViewModels;
using mvcForum.Core.Interfaces.Data;
using mvcForum.Core.Specifications;
using mvcForum.Web.Interfaces;

namespace mvcForum.Web.Areas.Forum.Controllers {

	/// <summary>
	/// Category controller.
	/// The controller handles showing a given category and the forums (and their sub-forums) belonging to that category.
	/// </summary>
	public class CategoryController : ThemedForumBaseController {
		private readonly IConfiguration config;
		private readonly IForumRepository forumRepo;

		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="uow"></param>
		/// <param name="userProvider"></param>
		/// <param name="config">Injected IConfiguration instance.</param>
		public CategoryController(IWebUserProvider userProvider, IContext context, IConfiguration config, IForumRepository forumRepo)
			: base(userProvider, context) {

			// Store the configuration instance as a variable on the controller instance.
			this.config = config;
			this.forumRepo = forumRepo;
		}

		#region Read
		/// <summary>
		/// The regular index/read method for a category.
		/// </summary>
		/// <param name="id">The Id of the category that should be shown.</param>
		/// <param name="title">The title of the category. At the moment this isn't used for anything.</param>
		/// <returns></returns>
		public ActionResult Index(Int32 id, String title) {
			// Get the category!
			Category category = this.GetRepository<Category>().Read(id);

			// Is the title correct?
			if (title != category.Name.ToSlug()) {
				// No, let's permanent redirect to the correct URL!
				return RedirectPermanent(
											Url.RouteUrl("ShowCategory", new {
												area = "forum",
												title = category.Name.ToSlug(),
												id = category.Id
											})
										);
			}

			// Create the model, we'll need to show it to the user in a bit.
			CategoryViewModel model = new CategoryViewModel(category);
			List<ForumViewModel> forumVMs = new List<ForumViewModel>();
			// Get the forums of the category.
			IEnumerable<Core.Forum> forums = this.forumRepo.ReadManyOptimized(new ForumSpecifications.SpecificCategoryNoParentForum(category));

			foreach (Core.Forum forum in forums.OrderBy(f => f.SortOrder)) {
				List<ForumViewModel> subForums = new List<ForumViewModel>();
				// If any sub-forums, let's get them too.
				foreach (Core.Forum subForum in forum.SubForums.OrderBy(f => f.SortOrder)) {
					// Add a sub-forum model to the collection.
					subForums.Add(new ForumViewModel(subForum, config.TopicsPerPage, this.config.AuthorNameSetting));
				}

				// Add a forum model to the collection, along with any sub-forums
				forumVMs.Add(new ForumViewModel(forum, config.TopicsPerPage, this.config.AuthorNameSetting) { SubForums = new ReadOnlyCollection<ForumViewModel>(subForums), Category = model });
			}
			model.Forums = new ReadOnlyCollection<ForumViewModel>(forumVMs);

			model.Path = new Dictionary<string, string>();
			// Create the breadcrumb path.
			HomeController.BuildPath(category, model.Path, this.Url);

			return View(model);
		}
		#endregion

		#region Misc
		/// <summary>
		/// The method marks all forums of the given category as read.
		/// </summary>
		/// <param name="id">Id of the category.</param>
		/// <returns></returns>
		[Authorize]
		[ActionName("Mark As Read")]
		public ActionResult MarkAsRead(Int32 id) {
			// Get the category!
			Category category = this.GetRepository<Category>().Read(id);
			// Let's iterate the sub-forums!
			foreach (var forum in category.Forums) {
				// Does the user have access to this forum?
				if (forum.HasAccess(AccessFlag.Read)) {
					// Yes, so let's track the forum (track the lastviewed date).
					forum.Track();
				}
			}

			// Done, back to the category view!
			return RedirectToAction("index", new { area = "forum", id = id, title = category.Name.ToSlug() });
		}
		#endregion
	}
}